{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "79f6b261-523d-4928-bb97-a9dc3588e7c1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# File: twist.ipynb\n",
    "# Code: Claude Code and Codex\n",
    "# Review: Ryoichi Ando (ryoichi.ando@zozo.com)\n",
    "# License: Apache v2.0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "24ef9f4b-2929-4e22-9d10-5ecff86ba720",
   "metadata": {},
   "outputs": [],
   "source": [
    "from frontend import App\n",
    "\n",
    "# create an app\n",
    "app = App.create(\"twist\")\n",
    "\n",
    "# create a cylinder mesh\n",
    "V, F = app.mesh.cylinder(r=0.5, min_x=-1.0, max_x=1.0, n=360)\n",
    "app.asset.add.tri(\"cylinder\", V, F)\n",
    "\n",
    "# create a scene\n",
    "scene = app.scene.create()\n",
    "\n",
    "# add cylinder with gradient coloring along axis\n",
    "obj = scene.add(\"cylinder\").cylinder_color([0, 0, 0], [1, 0, 0], [0, 1, 0])\n",
    "\n",
    "# set material properties\n",
    "(\n",
    "    obj.param.set(\"friction\", 0.0)\n",
    "    .set(\"bend\", 500)\n",
    "    .set(\"contact-gap\", 4e-3)\n",
    "    .set(\"young-mod\", 10000)\n",
    ")\n",
    "\n",
    "# define animation parameters for twisting and scaling\n",
    "angular_vel, move_delta, t_end = 360.0, 0.2, 10\n",
    "scale = 1 - t_end * 0.01\n",
    "\n",
    "# pin and animate left end\n",
    "(\n",
    "    obj.pin(obj.grab([-1, 0, 0]))\n",
    "    .spin(axis=[1, 0, 0], angular_velocity=angular_vel)\n",
    "    .scale(scale, t_start=0.0, t_end=t_end)\n",
    "    .move_by([move_delta, 0, 0], t_start=0.0, t_end=t_end)\n",
    ")\n",
    "\n",
    "# pin and animate right end in opposite direction\n",
    "(\n",
    "    obj.pin(obj.grab([1, 0, 0]))\n",
    "    .spin(axis=[-1, 0, 0], angular_velocity=angular_vel)\n",
    "    .scale(scale, t_start=0.0, t_end=t_end)\n",
    "    .move_by([-move_delta, 0, 0], t_start=0.0, t_end=t_end)\n",
    ")\n",
    "\n",
    "# compile the scene and report stats\n",
    "fixed = scene.build().report()\n",
    "\n",
    "# preview the initial scene\n",
    "fixed.preview()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b5eaa027-b3b5-451b-a565-9a3b1d05fe02",
   "metadata": {},
   "outputs": [],
   "source": [
    "# create a new session with the compiled scene\n",
    "session = app.session.create(fixed)\n",
    "\n",
    "# set session parameters - disable gravity and increase sparse matrix capacity\n",
    "(\n",
    "    session.param.set(\"dt\", 1 / 60)\n",
    "    .set(\"frames\", 430)\n",
    "    .set(\"gravity\", 0.0)\n",
    "    .set(\"csrmat-max-nnz\", 35000000)\n",
    ")  # 5GB VRAM needed\n",
    "\n",
    "# build this session\n",
    "fixed_session = session.build()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f0eb7eb2-ef73-4e76-90a4-882e6b94f228",
   "metadata": {},
   "outputs": [],
   "source": [
    "# start the simulation and live-preview the results\n",
    "fixed_session.start().preview()\n",
    "\n",
    "# also show simulation logs in realtime\n",
    "fixed_session.stream()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fd17ecf8-71bb-46e5-8ca6-4506d49b9fa7",
   "metadata": {},
   "outputs": [],
   "source": [
    "# create an animation from the simulation results\n",
    "fixed_session.animate()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5c8a6ac7-4ce9-4279-94a2-87edf015d42e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# export the animation to file\n",
    "fixed_session.export.animation()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a9de0b7e-f311-4a66-ac52-be315808121d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# this is for CI\n",
    "if app.ci:\n",
    "    assert fixed_session.finished()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
